package com.siemens.industrial.web.mvc.service.partner;

import com.siemens.industrial.model.partner.DeviceStatePeriod;
import com.siemens.industrial.utils.GlobalResponseCode;
import com.siemens.industrial.utils.SiemensException;
import com.siemens.industrial.web.mvc.dao.partner.PartnerDeviceStatePeriodDao;
import com.siemens.industrial.web.mvc.service.admin.ChartsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by qupen on 2016/8/31.
 */
@Service
public class PartnerDeviceStatePeriodService {
    @Resource
    PartnerDeviceStatePeriodDao partnerDeviceStatePeriodDao;

    @Resource
    ChartsService chartsService;

    public DeviceStatePeriod getDeviceStatePeriod(String tenantId, String deviceId, Date startTime) {
        return partnerDeviceStatePeriodDao.getDeviceStatePeriod(tenantId, deviceId, startTime);
    }

    public DeviceStatePeriod getDeviceStatePeriodByDevice(String tenantId, String deviceId) {
        return partnerDeviceStatePeriodDao.getDeviceStatePeriodInDevice(tenantId, deviceId);
    }

    public List<DeviceStatePeriod> getDeviceStatePeriods(String tenantId) {
        return partnerDeviceStatePeriodDao.getDeviceStatePeriods(tenantId);
    }

    public List<DeviceStatePeriod> getDeviceStatePeriodsByDevice(String tenantId, String deviceId) {
        return partnerDeviceStatePeriodDao.getDeviceStatePeriodsInDevice(tenantId, deviceId);
    }

    public List<DeviceStatePeriod> getDeviceStatePeriodsByTime(String tenantId, Date time) {
        return partnerDeviceStatePeriodDao.getDeviceStatePeriodsInTime(tenantId, time);
    }

    @Transactional
    public void saveDeviceStatePeriod(String tenantId, DeviceStatePeriod deviceStatePeriod) throws SiemensException {
        if (partnerDeviceStatePeriodDao.getDeviceStatePeriod(tenantId, deviceStatePeriod.getDeviceId(), deviceStatePeriod.getStartTime()) == null) {
            partnerDeviceStatePeriodDao.saveDeviceStatePeriod(tenantId, deviceStatePeriod);
        } else {
            throw new SiemensException(GlobalResponseCode.ERROR_STATE_EXISTED);
        }
    }

    @Transactional
    public void updateDeviceStatePeriod(String tenantId, DeviceStatePeriod deviceStatePeriod) throws SiemensException {
        if (partnerDeviceStatePeriodDao.getDeviceStatePeriod(tenantId, deviceStatePeriod.getDeviceId(), deviceStatePeriod.getStartTime()) == null) {
            partnerDeviceStatePeriodDao.updateDeviceStatePeriod(tenantId, deviceStatePeriod);
        } else {
            throw new SiemensException(GlobalResponseCode.ERROR_STATE_EXISTED);
        }
    }

    public List<Map<String, Object>> getPeriodsoftime(String tenantId, String deviceId, String startTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = sdf.parse(startTime);
        Calendar cal = Calendar.getInstance();
        cal.setTime(startDate);
        cal.add(Calendar.DATE, 1);
        Date endTime = cal.getTime();
        return partnerDeviceStatePeriodDao.getPeriodsoftime(tenantId, startDate, endTime, deviceId);
    }

    public List<Map<String, Object>> getPeriodsoftimeByCalculate(String tenantId, String deviceId, String startTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<Map<String, Object>> resultList = new ArrayList<>();
        List<Map<String, Object>> list = partnerDeviceStatePeriodDao.getDeviceStates(tenantId, deviceId, startTime);
        String timeString = (startTime + " 00:00:00");
        if (list.size() > 1) {    //确定有今天的数据
            if (!timeString.equals(list.get(1).get("start_time").toString())) {
                list.get(0).put("start_time", startTime + " 00:00:00");
            }
            resultList.add(list.get(0));
            for (int i = 1; i < list.size(); i++) {
                int last = resultList.size() - 1;
                if (list.get(i).get("state") == resultList.get(last).get("state")) {   //若当前数据状态与上一条状态相同,修改上一条数据结束时间   否则直接将当前数据添加
                    resultList.get(resultList.size() - 1).put("end_time", list.get(i).get("start_time"));
                    if (i == list.size() - 1) {
                        long minute = sdf.parse(list.get(i).get("start_time").toString()).getTime() - sdf.parse(resultList.get(last).get("start_time").toString()).getTime();
                        resultList.get(resultList.size() - 1).put("minute", minute / 1000);
                    }
                } else {   //到查出当天最后时间 数据去掉 不添加 直接返回
                    long minute = sdf.parse(list.get(i).get("start_time").toString()).getTime() - sdf.parse(resultList.get(last).get("start_time").toString()).getTime();
                    resultList.get(resultList.size() - 1).put("minute", minute / 1000);
                    resultList.get(resultList.size() - 1).put("end_time", list.get(i).get("start_time"));
                    if (i == list.size() - 1) {     //到查出当天最后时间 数据去掉 不添加 直接返回
                        return resultList;
                    }
                    resultList.add(list.get(i));
                }
            }
        }
        return resultList;
    }

    /**
     * 一台或者多台机床的状态时间统计的历史趋势
     *
     * @param tenantId
     * @param conditions
     * @return
     */
    private List<Map<String, Object>> getChartOneData(String tenantId, List<Map<String, Object>> conditions, String startTime, String endTime) {
        String param = "", view = "";
        if (conditions.size() > 0) {
            for (int i = 0; i < conditions.size(); i++) {
                if (i == conditions.size() - 1) {
                    param += "device_id='" + conditions.get(i).get("deviceId") + "'";
                } else {
                    param += "device_id='" + conditions.get(i).get("deviceId") + "' OR ";
                }
                if (i == 0) {
                    view += "SELECT date_id,'" + conditions.get(i).get("deviceId") + "' device_id FROM `" + tenantId + "`.v_num  WHERE date_id BETWEEN date('" + startTime + "') AND date('" + endTime + "')";
                } else {
                    view += " UNION ALL SELECT date_id,'" + conditions.get(i).get("deviceId") + "' device_id FROM `" + tenantId + "`.v_num WHERE date_id BETWEEN date('" + startTime + "') AND date('" + endTime + "')";
                }
            }
        }

        String sql = "SELECT \n" +
                "    f.date_id,\n" +
                "    f.device_id,\n" +
                "    f.on_line,\n" +
                "    f.off_line,\n" +
                "    g.device_unique_id\n" +
                "FROM(SELECT \n" +
                "    a.date_id, a.device_id, ifnull(b.on_line,0) on_line,ifnull( b.off_line,86400) off_line\n" +
                "FROM\n" +
                "    (" + view + ") a\n" +
                "        LEFT JOIN\n" +
                "    (SELECT \n" +
                "\t\t\tdevice_id,\n" +
                "            date_id,\n" +
                "            SUM(CASE\n" +
                "                WHEN state = 1 THEN `time_lag`\n" +
                "                ELSE 0\n" +
                "            END) AS on_line,\n" +
                "            SUM(CASE\n" +
                "                WHEN state = 0 THEN `time_lag`\n" +
                "                ELSE 0\n" +
                "            END) AS off_line\n" +
                "    FROM\n" +
                "        (SELECT \n" +
                "        device_id,\n" +
                "            DATE(start_time) date_id,\n" +
                "            state,\n" +
                "            SUM(TIMESTAMPDIFF(SECOND, start_time, end_time)) AS time_lag\n" +
                "    FROM\n" +
                "        `" + tenantId + "`.device_state_period\n" +
                "    WHERE\n" +
                "\t\t\tstart_time >= '" + startTime + "'\n" +
                "            AND end_time <= '" + endTime + "'\n" +
                "            AND (" + param + ")\n" +
                "    GROUP BY device_id , date_id , state) a\n" +
                "    GROUP BY device_id , date_id\n" +
                "    ORDER BY date_id) b ON a.date_id = b.date_id\n" +
                "        AND a.device_id = b.device_id) f\n" +
                "        LEFT JOIN\n" +
                "    `" + tenantId + "`.device g ON f.device_id = g.device_id\n" +
                "    order by date_id;";

        System.out.print(sql);
        return partnerDeviceStatePeriodDao.findChartOneData(sql);
    }

    /**
     * 机床状态柱状图数据
     */
    public Map<String, List<Map<String, Object>>> dataFormatOfMore(String tenantId, List<Map<String, Object>> conditions, String startTime, String endTime) {
        List<Map<String, Object>> maps = this.getChartOneData(tenantId, conditions, startTime, endTime);
        Map<String, List<Map<String, Object>>> deviceStateList = chartsService.deviceStateChartDataFormat(maps);
        return deviceStateList;
    }

    public List<Map<String, Object>> getTimePeriod(String tenantId, String startTime) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date startDate = sdf.parse(startTime);
            return partnerDeviceStatePeriodDao.findPeriodsofTime(tenantId, startDate);
        } catch (ParseException e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    public List<Map<String, Object>> getOneDayState(String tenantId, String startTime, String deviceId) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date startDate = sdf.parse(startTime);
        Calendar cal = Calendar.getInstance();
        cal.setTime(startDate);
        cal.add(Calendar.DATE, 1);
        Date endTime = cal.getTime();

        return partnerDeviceStatePeriodDao.findOneDayState(tenantId, startDate, endTime, deviceId);
    }

    public List<Map<String, Object>> getOneShiftState(String tenantId, String day, String startTime, String endTime, String deviceId) throws ParseException {
        return partnerDeviceStatePeriodDao.findTimePeriodState(tenantId, day, startTime, endTime, deviceId);
    }

    public void saveDownTime(String tenantId, String startTime, String endTime, String deviceId) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("");
        try {
            Date startDate = simpleDateFormat.parse(startTime);
            Date endDate = simpleDateFormat.parse(endTime);
            partnerDeviceStatePeriodDao.insertDownTime(tenantId, startDate, endDate, deviceId);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
}
